package com.euc.springbootframework.util;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Map.Entry;

public class NumberUtils extends org.apache.commons.lang3.math.NumberUtils{
    private static final int DEF_DIV_SCALE = 10;
    private static final Random random = new Random();


    private static final Map<Character,Character> encodeNumberMapping = new HashMap<>();
    private static final Map<Character,Character> decodeNumberMapping = new HashMap<>();

    static {
        encodeNumberMapping.put('1', '5');
        encodeNumberMapping.put('2', '7');
        encodeNumberMapping.put('3', '1');
        encodeNumberMapping.put('4', '6');
        encodeNumberMapping.put('5', '2');
        encodeNumberMapping.put('6', '8');
        encodeNumberMapping.put('7', '3');
        encodeNumberMapping.put('8', '9');
        encodeNumberMapping.put('9', '4');
        encodeNumberMapping.put('0', '0');
        for (Iterator<Entry<Character,Character>> iterator = encodeNumberMapping.entrySet().iterator(); iterator.hasNext();) {
            Entry<Character,Character> entry =  iterator.next();
            decodeNumberMapping.put(entry.getValue(), entry.getKey());
        }
    }

    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    public static double sub(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    public static double mul(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    public static double div(double v1, double v2) {
        return div(v1, v2, DEF_DIV_SCALE);
    }

    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static int randomNumber(int max,int min){
        return random.nextInt(max)%(max-min+1) + min;
    }

    public static String numberStringToString(String numberString){
        if(isNumber(numberString)){
            BigDecimal bd = new BigDecimal(numberString);
            return bd.toPlainString();
        }else{
            return numberString;
        }
    }

    public static Double decodeDouble(Double value,Character keyChar) {
        if(value == null) {
            return null;
        }
        value = NumberUtils.add(value,keyChar.toString().getBytes()[0]);
        char[] doubleChar = String.valueOf(value).toCharArray();
        for (int i = 0; i < doubleChar.length; i++) {
            Character c = doubleChar[i];
            if(StringUtils.isNumeric(c.toString())) {
                doubleChar[i] = decodeNumberMapping.get(doubleChar[i]);
            }
        }
        return Double.valueOf(String.valueOf(doubleChar));
    }



    public static Double encodeDouble(Double value,Character keyChar) {
        if(value == null) {
            return null;
        }
        char[] doubleChar = String.valueOf(value).toCharArray();
        for (int i = 0; i < doubleChar.length; i++) {
            Character c = doubleChar[i];
            if(StringUtils.isNumeric(c.toString())) {
                doubleChar[i] = encodeNumberMapping.get(doubleChar[i]);
            }
        }
        return NumberUtils.sub(Double.valueOf(String.valueOf(doubleChar)),keyChar.toString().getBytes()[0]);
    }
}
